<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>打包图</title>
  <script type="text/javascript" src="http://d3js.org/d3.v5.min.js"></script>
  <script src="../js/d3.tip.js"></script>
</head>

<body>
  <svg width="1462" height="1500"></svg>
</body>

<script>
  const svg = d3.select("svg");
  const width = svg.attr("width");
  const height = svg.attr("height");
  const margin = { left: 10, top: 10, right: 10, bottom: 10 };
  const innerWidth = width - margin.right - margin.left;
  const innerHeight = height - margin.top - margin.bottom;

  const maingroup = svg.append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  const data = {
    name: '中国一线城市',
    children: [
      {
        name: '北京',
        children: [
          {
            name: '东城区',
            value: 42
          },
          {
            name: '西城区',
            value: 51
          },
          {
            name: '朝阳区',
            value: 471
          },
          {
            name: '丰台区',
            value: 304
          },
          {
            name: '石景山区',
            value: 86
          },
          {
            name: '海淀区',
            value: 431
          },
          {
            name: '顺义区',
            value: 1021
          },
          {
            name: '通州区',
            value: 906
          },
          {
            name: '大兴区',
            value: 1036
          },
          {
            name: '房山区',
            value: 2019
          },
          {
            name: '门头沟区',
            value: 1451
          },
          {
            name: '昌平区',
            value: 1344
          },
          {
            name: '平谷区',
            value: 950
          },
          {
            name: '密云区',
            value: 2229
          },
          {
            name: '怀柔区',
            value: 2123
          },
          {
            name: '延庆区',
            value: 1994
          }
        ]
      },
      {
        name: '上海',
        children: [
          {
            name: '黄浦区',
            value: 20
          },
          {
            name: '徐汇区',
            value: 55
          },
          {
            name: '长宁区',
            value: 38
          },
          {
            name: '静安区',
            value: 37
          },
          {
            name: '普陀区',
            value: 56
          },
          {
            name: '虹口区',
            value: 23
          },
          {
            name: '杨浦区',
            value: 61
          },
          {
            name: '浦东新区',
            value: 1210
          },
          {
            name: '闵行区',
            value: 372
          },
          {
            name: '宝山区',
            value: 294
          },
          {
            name: '嘉定区',
            value: 464
          },
          {
            name: '金山区',
            value: 611
          },
          {
            name: '松江区',
            value: 605
          },
          {
            name: '青浦区',
            value: 676
          },
          {
            name: '奉贤区',
            value: 687
          },
          {
            name: '崇明区',
            value: 1411
          }
        ]
      },
      {
        name: '广州',
        children: [
          {
            name: '越秀区',
            value: 34
          },
          {
            name: '荔湾区',
            value: 59
          },
          {
            name: '海珠区',
            value: 90
          },
          {
            name: '天河区',
            value: 96
          },
          {
            name: '白云区',
            value: 796
          },
          {
            name: '黄埔区',
            value: 484
          },
          {
            name: '番禺区',
            value: 786
          },
          {
            name: '花都区',
            value: 970
          },
          {
            name: '南沙区',
            value: 527
          },
          {
            name: '增城区',
            value: 1616
          },
          {
            name: '从化区',
            value: 1974
          }
        ]
      },
      {
        name: '深圳',
        children: [
          {
            name: '福田区',
            value: 79
          },
          {
            name: '罗湖区',
            value: 79
          },
          {
            name: '南山区',
            value: 185
          },
          {
            name: '盐田区',
            value: 75
          },
          {
            name: '宝安区',
            value: 398
          },
          {
            name: '龙岗区',
            value: 388
          },
          {
            name: '龙华区',
            value: 176
          },
          {
            name: '坪山区',
            value: 167
          },
          {
            name: '光明新区',
            value: 155
          },
          {
            name: '大鹏新区',
            value: 295
          }
        ]
      }
    ]
  }


  // 处理数据，添加x.y,r，depth、parent等数据
  let root = d3.hierarchy(data)
    .sum(d => d.value)
    .sort(function (a, b) {
      return b.value - a.value
    })

  let pack = d3
    .pack() // 构建打包图
    .size([innerWidth - 2, innerHeight - 2])
    .padding(3)

  pack(root)

  // 返回后代节点数组
  let nodes = root.descendants();

  console.log(root);

  let colorScale = d3.scaleOrdinal(d3.schemeCategory10) // 通用线条的颜色

  let nodeGroup = maingroup
    .selectAll("g")
    .data(nodes)
    .enter()
    .append("g")
    .attr("transform", d => {
      return "translate(" + d.x + "," + d.y + ")"
    })
    .attr('class', function (d) {
      return (
        'node' + (!d.children ? ' node--leaf' : d.depth ? '' : ' node--root')
      )
    })
    .style('cursor', 'pointer')
    .style('fill-opacity', '0.8')
    .each(function (d) {
      d.node = this
    })
    .on("mouseover", hoverFn(true))
    .on("mouseout", hoverFn(false));



  /**
   * 添加圈圈
  */
  nodeGroup.append("circle")
    .attr('id', function (d) {
      console.log("d", d);
      return (
        'r' +
        Math.floor(d.r) +
        '-x' +
        Math.floor(d.x) +
        '-y' +
        Math.floor(d.y)
      ) // 用r+x+y生成唯一id，原创思路
    })
    .attr("fill", d => {
      return colorScale(d.depth)
    })
    .attr("r", d => d.r)

  /**
   * 添加圈圈内的文本
  */
  // 刷选出最后子节点 <g>
  let leaf = nodeGroup.filter(d => {
    return !d.children
  })

  let notLeaf = nodeGroup.filter(d => {
    return d.depth == 1
  })

  // 子级文本（无children）
  leaf.append("text")
    .attr("text-anchor", 'middle')
    .attr("writing-mode", 'vertical-rl')//横排从上到下
    .attr("text-orientation", 'upright')
    .attr("font-size", '10px')
    .attr("stroke", 'none')
    .text(d => d.data.name);

  // 父级文本
  notLeaf.append("text")
    .selectAll('tspan')
    .data(d => d.data.name)
    .enter()
    .append('tspan')
    .attr("fill", 'white')
    .attr("text-anchor", 'middle')
    .attr("font-size", '40px')
    .attr("font-weight", 'bolder')
    .attr('x', 0)
    .attr('y', function (d, i, nodes) {
      return 70 + (i - nodes.length / 2 - 0.5) * 70
    })
    .text(function (d) {
      return d
    })


  function hoverFn(hover) {
    return function (d) {
      console.log("dd:", d);
      d3.selectAll(
        d.ancestors().map(function (d) {
          return d.node
        })
      ).classed('node--hover', hover)
    }
  }

</script>
<style>
  .node--hover {
    stroke: black;
  }

</style>

</html>
